#include <netfwd.h>
#include <iobuffer.h>
#include <time_value.h>
#include <fileutil.h>

void test1()
{
	int count = 0;
	IOBuffer  content( 1 << 20 );

	FILE * fd = NULL;
	fd = fopen( "rbtree.h", "r+b" );

	while( 0 != ( count = fread( content.wr_ptr(), 1, content.wr_length(), fd ) ) )
	{
		content.wr_ptr( count );
	}

	fprintf( stderr, "content size %d\n", content.rd_length() );

	//content.rd_ptr( 6 );
	size_t nmemb = 12;

	FILE * out = fopen( "rbtree_bak.h", "w+b" );
	while( content.rd_length() > 0 )
	{
		count = fwrite( content.rd_ptr(), 1, nmemb, out );
		content.rd_ptr( count );
	}
	fclose( out );
	//content.rd_ptr( content.rd_length() );
	fclose( fd );
}
/*
void fbcopy( void *d, void *s, int i )
{
    _asm {
        mov ecx, i
        mov esi, s
        mov edi, d
        rep movsb
    }
}
*/

void * memcpy_tiny( void *dst, const void * src, size_t len )
{
    if (len <= 64) {
        register unsigned char *dd = (unsigned char*)dst + len;
        register const unsigned char *ss = (const unsigned char*)src + len;
        switch (len)
        {
        case 68:    *((int*)(dd - 68)) = *((int*)(ss - 68));
        case 64:    *((int*)(dd - 64)) = *((int*)(ss - 64));
        case 60:    *((int*)(dd - 60)) = *((int*)(ss - 60));
        case 56:    *((int*)(dd - 56)) = *((int*)(ss - 56));
        case 52:    *((int*)(dd - 52)) = *((int*)(ss - 52));
        case 48:    *((int*)(dd - 48)) = *((int*)(ss - 48));
        case 44:    *((int*)(dd - 44)) = *((int*)(ss - 44));
        case 40:    *((int*)(dd - 40)) = *((int*)(ss - 40));
        case 36:    *((int*)(dd - 36)) = *((int*)(ss - 36));
        case 32:    *((int*)(dd - 32)) = *((int*)(ss - 32));
        case 28:    *((int*)(dd - 28)) = *((int*)(ss - 28));
        case 24:    *((int*)(dd - 24)) = *((int*)(ss - 24));
        case 20:    *((int*)(dd - 20)) = *((int*)(ss - 20));
        case 16:    *((int*)(dd - 16)) = *((int*)(ss - 16));
        case 12:    *((int*)(dd - 12)) = *((int*)(ss - 12));
        case  8:    *((int*)(dd - 8)) = *((int*)(ss - 8));
        case  4:    *((int*)(dd - 4)) = *((int*)(ss - 4));
                    break;
        case 67:    *((int*)(dd - 67)) = *((int*)(ss - 67));
        case 63:    *((int*)(dd - 63)) = *((int*)(ss - 63));
        case 59:    *((int*)(dd - 59)) = *((int*)(ss - 59));
        case 55:    *((int*)(dd - 55)) = *((int*)(ss - 55));
        case 51:    *((int*)(dd - 51)) = *((int*)(ss - 51));
        case 47:    *((int*)(dd - 47)) = *((int*)(ss - 47));
        case 43:    *((int*)(dd - 43)) = *((int*)(ss - 43));
        case 39:    *((int*)(dd - 39)) = *((int*)(ss - 39));
        case 35:    *((int*)(dd - 35)) = *((int*)(ss - 35));
        case 31:    *((int*)(dd - 31)) = *((int*)(ss - 31));
        case 27:    *((int*)(dd - 27)) = *((int*)(ss - 27));
        case 23:    *((int*)(dd - 23)) = *((int*)(ss - 23));
        case 19:    *((int*)(dd - 19)) = *((int*)(ss - 19));
        case 15:    *((int*)(dd - 15)) = *((int*)(ss - 15));
        case 11:    *((int*)(dd - 11)) = *((int*)(ss - 11));
        case  7:    *((int*)(dd - 7)) = *((int*)(ss - 7));
                    *((int*)(dd - 4)) = *((int*)(ss - 4));
                    break;
        case  3:    *((short*)(dd - 3)) = *((short*)(ss - 3));
                    dd[-1] = ss[-1];
                    break;
        case 66:    *((int*)(dd - 66)) = *((int*)(ss - 66));
        case 62:    *((int*)(dd - 62)) = *((int*)(ss - 62));
        case 58:    *((int*)(dd - 58)) = *((int*)(ss - 58));
        case 54:    *((int*)(dd - 54)) = *((int*)(ss - 54));
        case 50:    *((int*)(dd - 50)) = *((int*)(ss - 50));
        case 46:    *((int*)(dd - 46)) = *((int*)(ss - 46));
        case 42:    *((int*)(dd - 42)) = *((int*)(ss - 42));
        case 38:    *((int*)(dd - 38)) = *((int*)(ss - 38));
        case 34:    *((int*)(dd - 34)) = *((int*)(ss - 34));
        case 30:    *((int*)(dd - 30)) = *((int*)(ss - 30));
        case 26:    *((int*)(dd - 26)) = *((int*)(ss - 26));
        case 22:    *((int*)(dd - 22)) = *((int*)(ss - 22));
        case 18:    *((int*)(dd - 18)) = *((int*)(ss - 18));
        case 14:    *((int*)(dd - 14)) = *((int*)(ss - 14));
        case 10:    *((int*)(dd - 10)) = *((int*)(ss - 10));
        case  6:    *((int*)(dd - 6)) = *((int*)(ss - 6));
        case  2:    *((short*)(dd - 2)) = *((short*)(ss - 2));
                    break;
        case 65:    *((int*)(dd - 65)) = *((int*)(ss - 65));
        case 61:    *((int*)(dd - 61)) = *((int*)(ss - 61));
        case 57:    *((int*)(dd - 57)) = *((int*)(ss - 57));
        case 53:    *((int*)(dd - 53)) = *((int*)(ss - 53));
        case 49:    *((int*)(dd - 49)) = *((int*)(ss - 49));
        case 45:    *((int*)(dd - 45)) = *((int*)(ss - 45));
        case 41:    *((int*)(dd - 41)) = *((int*)(ss - 41));
        case 37:    *((int*)(dd - 37)) = *((int*)(ss - 37));
        case 33:    *((int*)(dd - 33)) = *((int*)(ss - 33));
        case 29:    *((int*)(dd - 29)) = *((int*)(ss - 29));
        case 25:    *((int*)(dd - 25)) = *((int*)(ss - 25));
        case 21:    *((int*)(dd - 21)) = *((int*)(ss - 21));
        case 17:    *((int*)(dd - 17)) = *((int*)(ss - 17));
        case 13:    *((int*)(dd - 13)) = *((int*)(ss - 13));
        case  9:    *((int*)(dd - 9)) = *((int*)(ss - 9));
        case  5:    *((int*)(dd - 5)) = *((int*)(ss - 5));
        case  1:    dd[-1] = ss[-1];
                    break;
        case 0:
        default: break;
        }
        return dd;
    }
    else {
        return memcpy( dst, src, len );
    }
}

void test3()
{
    Time_Value start = Time_Value::timeofday();

    char to_buf[64] = {0};
    char from_buf[64] = {0};

    char * to = to_buf;
    char * from = from_buf;
    for( int32_t i = 0; i < ( 1 << 20 ); ++i )
    {
        //memmove( to, to+1, 63 );
        memcpy( to, to+1, 63 );
        //memcpy_tiny( to, from, 64 );
    }

    Time_Value stop = Time_Value::timeofday();
    stop -= start;
    fprintf( stderr, "use time (%lu)seconds:(%lu)usecs\n", stop.sec(), stop.usec() );
}

void test2()
{
	Time_Value start = Time_Value::timeofday();
	IOBuffer content( 1 << 18 );
	content.wr_ptr( 1 << 18 );
	while( content.rd_length()  > 0 )
		content.rd_ptr( 1 );

    Time_Value stop = Time_Value::timeofday();
    stop -= start;
    fprintf( stderr, "use time (%lu)seconds:(%lu)usecs\n", stop.sec(), stop.usec() );
	return;
}

void test4()
{
    Time_Value start = Time_Value::timeofday();

	// 256k
    char buf[262144] = {0};
    char * to = buf;

    for( int32_t i = 1; i < 262144; i+=48 )
    {
        char * dirft = to + i;
        memmove( to, dirft, 262144-i );
        //memcpy( to, dirft, 262144-i );
    }

    Time_Value stop = Time_Value::timeofday();
    stop -= start;
    fprintf( stderr, "use time (%lu)seconds:(%lu)usecs\n", stop.sec(), stop.usec() );
}

void test5()
{
	int count = 0;
	IOBuffer content;

    int32_t write_total = 0;

	FILE * fd = NULL;
	fd = fopen( "rbtree.h", "r+b" );
    FILE * out = fopen( "rbtree_bak.h", "w+b" );

	while( 0 != ( count = fread( content.wr_ptr(), 1, content.wr_length(), fd ) ) )
	{
        size_t nmemb = 90;
		content.wr_ptr( count );
        fprintf( stderr, "read from file size %d\n", content.rd_length() );
        int32_t write_bytes = content.rd_length();
        while( write_bytes > 0 )
        {
            count = fwrite( content.rd_ptr(), 1, nmemb, out );
            if( count <= 0 )
            {
                //fprintf( stderr, "error %s\n", strerror(errno) );
                //return;
            }
            write_total += count;
            write_bytes -= count;
            //fprintf( stderr, "count = %d write_total = %d nmemb = %d\n", count, write_total, nmemb );
            //sleep(1);
            content.rd_ptr( count );
            if( write_bytes < nmemb )
                nmemb = write_bytes;
        }
        fprintf( stderr, "can write size %d\n", content.wr_length() );
	}

    fprintf( stderr, "write_total = %d\n", write_total );

	fclose( out );
	fclose( fd );
}

void test6()
{
	IOBuffer io_buffer( 64 );
	std::cout << "\n-------------------\nio_buffer rd_length=" << io_buffer.rd_length() << std::endl;
	std::cout << "io_buffer wr_length=" << io_buffer.wr_length() << std::endl;
	std::cout << "io_buffer capacity=" << io_buffer.capacity() << std::endl;

	char buf[128];
	memset( buf, '1', 128 );
	memcpy( io_buffer.wr_ptr(), buf, 28 );
	io_buffer.wr_ptr( 28 );

	std::cout << "\n-------------------\nio_buffer rd_length=" << io_buffer.rd_length() << std::endl;
	std::cout << "io_buffer wr_length=" << io_buffer.wr_length() << std::endl;
	std::cout << "io_buffer capacity=" << io_buffer.capacity() << std::endl;

	io_buffer.rd_ptr( 28 );
	std::cout << "\n-------------------\nio_buffer rd_length=" << io_buffer.rd_length() << std::endl;
	std::cout << "io_buffer wr_length=" << io_buffer.wr_length() << std::endl;
	std::cout << "io_buffer capacity=" << io_buffer.capacity() << std::endl;

	memcpy( io_buffer.wr_ptr(), buf, 100 );
	io_buffer.wr_ptr( 100 );
	std::cout << "\n-------------------\nio_buffer rd_length=" << io_buffer.rd_length() << std::endl;
	std::cout << "io_buffer wr_length=" << io_buffer.wr_length() << std::endl;
	std::cout << "io_buffer capacity=" << io_buffer.capacity() << std::endl;

    io_buffer.rd_ptr( 100 );
	std::cout << "\n-------------------\nio_buffer rd_length=" << io_buffer.rd_length() << std::endl;
	std::cout << "io_buffer wr_length=" << io_buffer.wr_length() << std::endl;
	std::cout << "io_buffer capacity=" << io_buffer.capacity() << std::endl;

}

void test7()
{
	int count = 0;
	IOBuffer content;

    int32_t write_total = 0;

	FILE * fd = NULL;
	fd = fopen( "rbtree.h", "r+b" );
    int32_t num_fd = fileno( fd );
    struct stat buf;
    fstat( num_fd, &buf );
    int32_t file_size = buf.st_size;
    fprintf( stderr, "rbtree_bak.h size = %d\n", file_size );

    FILE * out = fopen( "rbtree_bak1.h", "w+b" );

	while( file_size > 0 )
	{
        count = fread( content.wr_ptr(), 1, content.wr_length(), fd );
        if( count > 0 )
        {
            fprintf( stderr, "read %d bytes\n", count );
            content.wr_ptr( count );
        }

        if( content.rd_length() >= 1024 )
            count = fwrite( content.rd_ptr(), 1, 1024, out );
        else
            count = fwrite( content.rd_ptr(), 1, content.rd_length(), out );
        if( count > 0 )
        {
            content.rd_ptr( count );
            file_size -= count;
            fprintf( stderr, "write %d remain %d\n", count, file_size );
        }
	}

	fclose( out );
	fclose( fd );
}

int main()
{
	time_t start = time(NULL);
	//test5();
	test7();
	fprintf( stderr, "use seconds(%lu)\n", time(NULL) - start );
	return 0;
}
